/**
 * ReportGear(2011)
 */
package com.reportgear.designer.applet;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.List;

import javax.swing.BorderFactory;
import javax.swing.JApplet;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JToolBar;
import javax.swing.JTree;
import javax.swing.SwingConstants;
import javax.swing.SwingUtilities;
import javax.swing.UIManager;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.TreeNode;

import netscape.javascript.JSObject;

import com.reportgear.core.data.SalaryHelper;
import com.reportgear.core.data.model.SalaryDataObject;
import com.reportgear.core.swing.layout.LayoutHelper;
import com.reportgear.core.swing.pane.base.JBaseDialog;
import com.reportgear.core.swing.pane.base.JBasePane;
import com.reportgear.designer.ui.toolbar.ShowToolBar;
import com.reportgear.report.context.ReportContext;
import com.reportgear.report.context.salary.SalaryObjectGroupInfoPane;
import com.reportgear.report.core.api.idname.DefaultIdName;
import com.reportgear.report.core.api.idname.IdName;
import com.reportgear.report.model.ReportModel;
import com.reportgear.report.model.SalaryReportModel;
import com.reportgear.report.model.calculator.CalculatorHelper;
import com.reportgear.report.model.cell.value.salary.SalaryObjectType;
import com.reportgear.report.model.cell.value.support.CommonObject;
import com.reportgear.report.setting.AppletSettings;
import com.reportgear.report.setting.ApplicationContext;
import com.reportgear.report.view.JWorksheet;
import com.reportgear.swing.controls.JTreeComboBox;
import com.reportgear.swing.util.GuiUtils;

/**
 * 设计器Applet
 * 
 * @version 1.0 2011-4-16
 * @author <a herf="lexloo@gmail.com">lexloo</a>
 * @since Report 1.0
 */
public class SctcApplet extends JApplet {
	/**
	 * UID
	 */
	private static final long serialVersionUID = -853388665196164659L;

	public void init() {
		ApplicationContext.INSTANCE.setApplet(true);
		AppletSettings appletSettings = AppletSettings.INSTANCE;

		appletSettings.setJsObject(JSObject.getWindow(this));

		initComponents();
	}

	public void start() {

	}

	public void stop() {
	}

	public void destroy() {
	}

	private void initComponents() {
		try {
			UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
		} catch (Exception e) {
			e.printStackTrace();
		}

		GuiUtils.setDefaultUIFont("宋体");

		this.setLayout(new BorderLayout());
		this.setBackground(Color.WHITE);
	}

	/**
	 * 打印发放表
	 * 
	 * @param paymentId
	 *            发放表Id
	 */
	public void printPayment(int paymentId) {
		TemplateSelectPane pane = new TemplateSelectPane(paymentId);

		if (JBaseDialog.RESULT_OK == pane.showDialog(SwingUtilities.getWindowAncestor(this), "选择模板", 400, 180)) {
			IdName<Integer> select = pane.getSelected();
			if (select == null) {
				JOptionPane.showMessageDialog(null, "请选择使用的模板");
				return;
			}

			print(paymentId, select.getId());
		}
	}

	private void print(int payId, int templateId) {
		ParamsInfoPane pane = new ParamsInfoPane();

		if (JBaseDialog.RESULT_OK == pane.showDialog(SwingUtilities.getWindowAncestor(this), "确定对象", 460, 330)) {
			ReportContext ctx = ReportContext.INSTANCE;

			ctx.setPaymentId(payId);
			ctx.setShowLevelList(pane.getShowLevel());
			ctx.setGroupLevel(pane.getGroupLevel());
			ctx.setUseSelectedObject(pane.isUseSelectedObject());
			ctx.setSelectedObjectId(pane.getObjectId());
			ctx.setSalaryObjectType(pane.getSalaryObjectType());

			String template = SalaryHelper.INSTANCE.loadTemplate(templateId);
			ReportModel model = new SalaryReportModel();
			model.fromXmlString(template);

			show(model);
		}
	}

	private void show(ReportModel model) {
		ReportModel currReport = CalculatorHelper.calculateSalaryReportModel(model);
		JWorksheet sheet = new JWorksheet(currReport);
		ReportContext.INSTANCE.setCurrentWorkSheet(sheet);
		this.add(sheet, BorderLayout.CENTER);
		JToolBar styleBar = new ShowToolBar();
		this.add(styleBar, BorderLayout.NORTH);
	}

	private static class TemplateSelectPane extends JBasePane {
		private JComboBox cbxTemplate;
		private int paymentId;

		public TemplateSelectPane(int paymentId) {
			this.paymentId = paymentId;

			this.initComponents();
		}

		@SuppressWarnings("unchecked")
		public IdName<Integer> getSelected() {
			return (IdName<Integer>) this.cbxTemplate.getSelectedItem();
		}

		/**
		 * 初始化组件
		 */
		private void initComponents() {
			this.setLayout(new GridBagLayout());
			this.setBorder(BorderFactory.createEtchedBorder());

			this.add(new JLabel("打印模板", SwingConstants.LEFT), LayoutHelper.newGridBagConstraints(0, 0, 1, 1));
			cbxTemplate = this.createTemplateListBox(this.paymentId);
			this.add(cbxTemplate, LayoutHelper.newGridBagConstraints(1, 0, 1, 1));
			cbxTemplate.setPreferredSize(new Dimension(300, 24));
		}

		private JComboBox createTemplateListBox(int paymentId) {
			List<IdName<Integer>> reportList = new ArrayList<IdName<Integer>>();

			List<SalaryDataObject> templateList = SalaryHelper.INSTANCE.loadTemplateList();
			SalaryDataObject currPayBase = SalaryHelper.INSTANCE.getPayBase(paymentId);
			int id = currPayBase.getInt("systemID");
			for (SalaryDataObject sdo : templateList) {
				if (id == sdo.getInt("systemID")) {
					reportList.add(new DefaultIdName<Integer>(sdo.getInt("id"), sdo.getString("name")));
				}
			}

			JComboBox cbxTemplate = new JComboBox(reportList.toArray());

			return cbxTemplate;
		}
	}

	private static class ParamsInfoPane extends JBasePane {
		private SalaryObjectGroupInfoPane paramPane;
		private JCheckBox chkObject;
		private JTreeComboBox cbxItem = new JTreeComboBox();
		private SalaryObjectType currSalaryobjectType = null;

		public ParamsInfoPane() {
			this.setLayout(new GridBagLayout());
			this.setBorder(BorderFactory.createEtchedBorder());

			paramPane = new SalaryObjectGroupInfoPane();
			this.add(paramPane, LayoutHelper.newGridBagConstraints(0, 0, 2, 1));

			this.add(new JLabel("指定打印对象"), LayoutHelper.newGridBagConstraints(0, 1, 1, 1));
			chkObject = new JCheckBox();
			this.add(chkObject, LayoutHelper.newGridBagConstraints(1, 1, 1, 1));
			chkObject.addActionListener(new ActionListener() {

				@Override
				public void actionPerformed(ActionEvent evt) {
					JCheckBox chk = (JCheckBox) evt.getSource();

					cbxItem.setEnabled(chk.isSelected());

					// 是否要填充下拉框
					if (chk.isSelected()) {
						if (currSalaryobjectType != paramPane.getSalaryObjectType()) {
							currSalaryobjectType = paramPane.getSalaryObjectType();
							refreshItems(currSalaryobjectType);
						}
					}
				}
			});

			this.add(new JLabel("成本中心(组织机构)"), LayoutHelper.newGridBagConstraints(0, 2, 1, 1));
			cbxItem.setPreferredSize(new Dimension(300, 24));
			cbxItem.setEnabled(false);
			this.add(cbxItem, LayoutHelper.newGridBagConstraints(1, 2, 1, 1));
			// cbxItem.addFocusListener(new FocusListener() {
			//
			// @Override
			// public void focusGained(FocusEvent e) {
			// // 暂时用获取焦点来判断是否需要重新加载数据
			// if (currSalaryobjectType != paramPane.getSalaryObjectType()) {
			// currSalaryobjectType = paramPane.getSalaryObjectType();
			// refreshItems(currSalaryobjectType);
			// }
			// }
			//
			// @Override
			// public void focusLost(FocusEvent e) {
			// }
			// });
		}

		/**
		 * 更新薪酬项目
		 * 
		 * @param objectType
		 *            对象id
		 */
		private void refreshItems(SalaryObjectType objectType) {
			List<CommonObject> items = this.loadItems(objectType);

			DefaultMutableTreeNode root = new DefaultMutableTreeNode(objectType);
			DefaultMutableTreeNode pNode = null;

			for (CommonObject o : items) {
				DefaultMutableTreeNode node = new DefaultMutableTreeNode(o);
				if ((pNode != null) && ((CommonObject) pNode.getUserObject()).getId() == o.getParentId()) {
					pNode.add(node);
				} else {
					pNode = this.searchParentNode(root, o);
					if (pNode == null) {
						root.add(node);
					} else {
						pNode.add(node);
					}
				}
			}

			JTree tree = new JTree(root);
			cbxItem.setTree(tree);
		}

		/**
		 * 加载发放表对象信息
		 * 
		 * @param objectType
		 *            对象类型
		 * @return 对象信息
		 */
		private List<CommonObject> loadItems(SalaryObjectType objectType) {
			List<SalaryDataObject> sdoList;

			if (objectType == SalaryObjectType.ORGANIZATION) {
				sdoList = SalaryHelper.INSTANCE.getOrgs();
			} else {
				sdoList = SalaryHelper.INSTANCE.getCenters();
			}

			List<CommonObject> items = new ArrayList<CommonObject>();
			for (SalaryDataObject sdo : sdoList) {
				items.add(new CommonObject(sdo.getInt("id"), sdo.getInt("parentId"), sdo.getString("code"), sdo
						.getString("name")));
			}

			Collections.sort(items);

			return items;
		}

		@SuppressWarnings("unchecked")
		private DefaultMutableTreeNode searchParentNode(TreeNode root, CommonObject co) {
			int pid = co.getParentId();
			DefaultMutableTreeNode node = null;
			DefaultMutableTreeNode rootNode = (DefaultMutableTreeNode) root;

			Enumeration e = rootNode.breadthFirstEnumeration();
			while (e.hasMoreElements()) {
				node = (DefaultMutableTreeNode) e.nextElement();
				Object o = node.getUserObject();
				if (o instanceof CommonObject) {
					if (((CommonObject) o).getId() == pid) {
						return node;
					}
				}
			}

			return null;
		}

		/**
		 * 获取分组层级
		 * 
		 * @return 分组层级
		 */
		public int getGroupLevel() {
			return this.paramPane.getGroupLevel();
		}

		public boolean isUseSelectedObject() {
			return this.chkObject.isSelected();
		}

		public int getObjectId() {
			DefaultMutableTreeNode selectNode = cbxItem.getSelectedTreeNode();

			if (selectNode == null) {
				return 0;
			}

			return ((CommonObject) selectNode.getUserObject()).getId();
		}

		/**
		 * 获取显示层级
		 * 
		 * @return 显示层级
		 */
		public List<Integer> getShowLevel() {
			return this.paramPane.getShowLevel();
		}

		/**
		 * 获取薪酬对象类型
		 * 
		 * @return 薪酬对象类型
		 */
		public SalaryObjectType getSalaryObjectType() {
			return this.paramPane.getSalaryObjectType();
		}
	}
}
